package cn.car.carguanli.websocket;

import cn.car.carguanli.model.LocationData;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
@ServerEndpoint("/websocket/location")
public class LocationWebSocket {
    private static RedisTemplate<String, Object> redisTemplate;

    @Autowired
    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        LocationWebSocket.redisTemplate = redisTemplate;
    }

    // Redis中位置数据的过期时间（120秒）
    private static final long LOCATION_EXPIRE_TIME = 120;

    private static final CopyOnWriteArraySet<LocationWebSocket> webSocketSet = new CopyOnWriteArraySet<>();
    private Session session;

    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        webSocketSet.add(this);
        log.info("有新的连接加入，当前连接数：{}", webSocketSet.size());
    }

    @OnClose
    public void onClose() {
        webSocketSet.remove(this);
        log.info("有连接关闭，当前连接数：{}", webSocketSet.size());
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("收到客户端消息：{}", message);
        try {
            LocationData locationData = JSON.parseObject(message, LocationData.class);
            if (locationData != null && locationData.getId() != null) {
                // 记录当前时间戳
                long currentTime = System.currentTimeMillis();

                // 只使用一个键存储位置数据，同时保存时间戳
                String locationKey = "location:" + locationData.getId();

                // 创建包含完整信息的位置记录
                String locationRecord = JSON.toJSONString(new LocationRecord(
                    locationData.getId(),
                    locationData.getLongitude(),
                    locationData.getLatitude(),
                    currentTime
                ));

                // 将记录添加到Redis列表中
                redisTemplate.opsForList().rightPush(locationKey, locationRecord);

                // 为位置数据设置2分钟的过期时间
                redisTemplate.expire(locationKey, LOCATION_EXPIRE_TIME, TimeUnit.SECONDS);

                // 不再发送确认消息给客户端
                // 只在日志中记录
                log.debug("位置数据已成功保存，ID: {}，将在{}秒后过期", locationData.getId(), LOCATION_EXPIRE_TIME);
            }
        } catch (Exception e) {
            log.error("处理消息出错：", e);
            try {
                sendMessage("数据处理失败：" + e.getMessage());
            } catch (IOException ex) {
                log.error("发送错误消息失败：", ex);
            }
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误：", error);
    }

    private void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    // 广播消息给所有连接的客户端
    public void broadcastMessage(String message) {
        for (LocationWebSocket webSocket : webSocketSet) {
            try {
                webSocket.sendMessage(message);
            } catch (IOException e) {
                log.error("广播消息失败：", e);
            }
        }
    }

    // 位置记录内部类
    public static class LocationRecord {
        private String id;
        private Double longitude;
        private Double latitude;
        private Long timestamp;

        public LocationRecord(String id, Double longitude, Double latitude, Long timestamp) {
            this.id = id;
            this.longitude = longitude;
            this.latitude = latitude;
            this.timestamp = timestamp;
        }

        // Getters
        public String getId() { return id; }
        public Double getLongitude() { return longitude; }
        public Double getLatitude() { return latitude; }
        public Long getTimestamp() { return timestamp; }
    }
}